
// import * as d3 from "../lib/d3.js";
import * as d3 from "d3";
import {$} from "../util/seq.js";
import {defineHandleButton} from "./buttons.js";
import {whenEnabled} from "./util.js";
import {formatAsDecimalDegrees} from "../util/strings.js";
import {ø} from "../util/objects.js";
import {first} from "underscore";

export function activeUnits(layer, selected_units) {
    const {unitDescriptors = {}} = layer ?? {};
    const symbol = selected_units?.[layer?.type] ?? first(Object.keys(unitDescriptors));
    return unitDescriptors[symbol];
}

/**
 * @param container
 * @param {Handle} spotlight_coords
 */
export function defineSpotlight(container, spotlight_coords) {
    const coords = container.select("[data-name=spotlight-coords]");

    function updateDOM(value) {
        container.property("hidden", value === undefined);
        coords.text(formatAsDecimalDegrees(value,4));
    }

    updateDOM(spotlight_coords.get());
    spotlight_coords.on($`change`, updateDOM);

    defineHandleButton(container.selectAll("[data-name=hide-spotlight]"), spotlight_coords, () => undefined);
}

/**
 * @param container
 * @param {Handle} spotlight_coords
 * @param {Handle} selected_units
 * @param {Handle} interpolation_type
 * @param layerAgent
 */
export function defineLayerSpotlight(container, spotlight_coords, selected_units, interpolation_type, layerAgent) {
    const field = container.select("[aria-label]");
    const button = container.select("button");
    const buttonContent = button.select("span");

    function updateDOM() {
        const layer = layerAgent.value();
        const units = activeUnits(layer, selected_units.get());
        const [λ = NaN, φ = NaN] = spotlight_coords.get() ?? [];
        const interpolate = layer?.field?.()[interpolation_type.get()];
        const val = interpolate?.(λ, φ);
        const {formattedVal = "", fullText = ""} = units?.format(val) ?? {};

        container.property("hidden", formattedVal === "" || !units);
        field.attr("aria-label", fullText).text(formattedVal);
        buttonContent.html(units?.html ?? "");
    }

    function updateStore() {
        const layer = layerAgent.value() ?? {};
        const {unitDescriptors = {}} = layer;
        const symbols = Object.keys(unitDescriptors);
        if (symbols.length > 0) {
            selected_units.getAndSet((selected = {}) => {
                const currentSymbol = selected[layer.type] ?? first(symbols);
                const currentIndex = symbols.indexOf(currentSymbol);
                const nextIndex = (currentIndex + 1) % symbols.length;
                const nextSymbol = symbols[nextIndex];
                return ø(selected, {[layer.type]: nextSymbol});
            });
        }
    }

    updateDOM();
    selected_units.on($`change`, updateDOM);
    spotlight_coords.on($`change`, updateDOM);
    layerAgent.on($`update`, updateDOM);
    button.on($`click`, whenEnabled(updateStore));
}

/**
 * @param svg
 * @param globeAgent
 * @param fieldAgent
 * @param {Handle} spotlight_coords
 * @param inputController
 */
export function defineSpotlightMarker(svg, globeAgent, fieldAgent, spotlight_coords, inputController) {

    function updateDOM() {
        const globe = globeAgent.value();
        const [λ, φ] = spotlight_coords.get() ?? [NaN, NaN];
        if (!globe || λ !== λ || φ !== φ) {
            svg.select(".location-mark").remove();
            return;
        }
        const path = d3.geoPath().projection(globe.projection).pointRadius(7);
        let mark = svg.select(".location-mark");
        if (!mark.node()) {
            mark = svg.append("path").classed("location-mark", true);
        }
        mark.datum({type: "Point", coordinates: [λ, φ]}).attr("d", path);
    }

    function updateStore(point) {
        const globe = globeAgent.value();
        const field = fieldAgent.value();
        const x = +point?.[0];
        const y = +point?.[1];

        if (!globe || !field || x !== x || y !== y || !field.isInsideBoundary(x, y)) {
            return;
        }

        const coord = globe.projection.invert([x, y]) ?? [];
        const λ = +coord[0];
        const φ = +coord[1];
        if (λ === λ && φ === φ) {
            spotlight_coords.set([λ, φ]);
        }
    }

    spotlight_coords.on($`change`, updateDOM);
    globeAgent.on($`update`, updateDOM);
    inputController.on($`click`, updateStore);
}
